import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.simpleframework.xml.*;
import org.simpleframework.xml.core.Persister;

import java.io.File;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 配置文件的实体类
 * Created by LuoTao on 2016/10/26.
 * LemonTech Copyright reserved.
 */
@Root(name = "MonitorConfig", strict = false)
class MonitorConfig {
    private static Logger logger = LogManager.getLogger(MonitorConfig.class);
    @ElementList(name = "Config", inline = true)
    private List<Config> configList;
    @Attribute(required = false)
    private String reportName = System.currentTimeMillis() + "_监控报告";
    @Element(required = false)
    private String author;
    @Element(required = false)
    private String title;

    /**
     * 将配置实体化
     *
     * @param configName 配置文件名
     * @return 配置的实体对象
     */
    public static MonitorConfig getConfig(String configName) {
        Serializer config = new Persister();
        try {
//            return config.read(MonitorConfig.class, MonitorConfig.class.getResourceAsStream(configName));
            return config.read(MonitorConfig.class, new File(configName));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public List<Config> getConfigList() {
        return configList;
    }

    public void setConfigList(List<Config> configList) {
        this.configList = configList;
    }

    public String getAuthor() {
        if (author == null) {
            return "成都柠檬时光科技有限公司";
        }
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getTitle() {
        if (title == null) {
            return "监控报告";
        }
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getReportName() {
        return reportName;
    }

    public void setReportName(String reportName) {
        this.reportName = reportName;
    }
}

@Root(name = "Config")
class Config {
    private static Logger logger = LogManager.getLogger(Config.class);
    @Element
    private String jdbc;
    @Element
    private String host;
    @Element(required = false, data = true)
    private String username;
    @Element(required = false, data = true)
    private String password;
    @Element
    private String database;
    @Element(required = false)
    private String DBalias;
    @Element(required = false)
    private String author;
    @Element(required = false)
    private String date;
    @ElementList(name = "query", inline = true)
    private List<query> queryList;
    @ElementMap(required = false, key = "varName", value = "varValue",
            inline = true, keyType = String.class, valueType = String.class, entry = "var")
    private LinkedHashMap<String, String> vars;

    public String getJdbc() {
        return jdbc;
    }

    public void setJdbc(String jdbc) {
        this.jdbc = jdbc;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getDatabase() {
        return database;
    }

    public void setDatabase(String database) {
        this.database = database;
    }

    public String getDBalias() {
        if (DBalias == null) {
            return database;
        }
        return DBalias;
    }

    public void setDBalias(String DBalias) {
        this.DBalias = DBalias;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public List<query> getQueryList() {
        return queryList;
    }

    public void setQueryList(List<query> queryList) {
        this.queryList = queryList;
    }

    public LinkedHashMap<String, String> getVars() {
        return vars;
    }

    public void setVars(LinkedHashMap<String, String> vars) {
        this.vars = vars;
    }
}

@Root(name = "query")
class query {
    private static Logger logger = LogManager.getLogger(query.class);
    @Element
    private String name;
    @Element
    private String note;
    @Element
    private String sql;
    @Element(required = false, name = "transpose")
    private Boolean needTranspose;
    @ElementMap(required = false, key = "varName", value = "varValue",
            inline = true, keyType = String.class, valueType = String.class, entry = "var")
    private LinkedHashMap<String, String> vars = null;
    @ElementMap(required = false, key = "originName", value = "newName",
            inline = true, keyType = String.class, valueType = String.class, entry = "rename")
    private HashMap<String, String> translate = null;
    //用于区别每个query
    private String UUID = java.util.UUID.randomUUID().toString();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    public Boolean getNeedTranspose() {
        return needTranspose;
    }

    public void setNeedTranspose(Boolean needTranspose) {
        this.needTranspose = needTranspose;
    }

    public String getSql(Config config) {
        if (this.vars == null) {
            this.vars = config.getVars();
        } else if (config.getVars() != null) {
            for (Map.Entry<String, String> toAdd : config.getVars().entrySet()) {
                if (!this.vars.containsKey(toAdd.getKey())) {
                    this.vars.put(toAdd.getKey(), toAdd.getValue());
                }
            }
        }
        if (vars != null && vars.size() != 0) {
            Pattern pattern = Pattern.compile("\\$\\{[^\\{]*\\}");
            Matcher matcher = pattern.matcher(sql);
            String newSql = sql;
            while (matcher.find()) {
                String matchString = matcher.group();
                String varName = matchString.substring(2, matchString.length() - 1);
                if (!vars.containsKey(varName)) {
                    logger.error("SQL中的变量" + varName + "未在变量区域中定义或定义错误");
                } else {
                    //将数据中的变量对应替换
                    try {
                        newSql = newSql.replaceAll("\\$\\{" + varName + "\\}", vars.get(varName));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            return newSql;
        }
        logger.error("SQL中的变量未定义！");
        return sql;
    }

    public void setSql(String sql) {
        this.sql = sql;
    }

    public LinkedHashMap<String, String> getVars() {
        return vars;
    }

    public void setVars(LinkedHashMap<String, String> vars) {
        this.vars = vars;
    }

    public HashMap<String, String> getTranslate() {
        return translate;
    }

    public void setTranslate(HashMap<String, String> translate) {
        this.translate = translate;
    }
}